﻿#ifndef switch_h__
#define switch_h__


/************************************************************************/
/* 日志模块数据定义                                                     */
/************************************************************************/
typedef enum log_level_t
{
    LOG_LVL_ERROR = 1,
    LOG_LVL_WARNING,
    LOG_LVL_INFO,
    LOG_LVL_DETAILS,
    LOG_LVL_DEBUG
}log_level_t;

typedef enum log_group_t
{
    LOG_GRP_ALL = 1,
    LOG_GRP_SW,
}log_group_t;

#define LOG_LVL_DEFAULT LOG_LVL_DEBUG

extern enum log_group_t _log_group;
extern enum log_level_t _log_level;

typedef struct log_entry
{
    enum log_group_t _grp;
    enum log_level_t _lvl;
    int8_t *_time;
    int8_t *_log;
}log_entry_t;

//将log_level_t和log_group_t转换为字符串

#define GET_LOG_LEVEL(lvl) (\
    (lvl == LOG_LVL_ERROR)? "ERROR": \
    (lvl == LOG_LVL_WARNING)? "WARNING": \
    (lvl == LOG_LVL_INFO)? "DEBUG":\
    (lvl == LOG_LVL_INFO)? "INFO": \
    (lvl == LOG_LVL_DETAILS)? "DETAILS": \
    "LOG_LVL_UNKNOWN")

#define GET_LOG_GROUP(grp) (\
    (grp == LOG_GRP_ALL)? "ALL": \
    (grp == LOG_GRP_SW)? "SWITCH": \
    "UNKNOWN")

/************************************************************************/
/* 内部通讯数据定义                                                     */
/************************************************************************/
#define TASK_DATA_MAX_SIZE 1024 //线程通信的最大数据长度
#define TASK_TTL_MAX        32  //最多进行32次交换

// 线程名定义
#define NAME_SWITCH     "SW  \0" //交换线程，注意用空格补齐4字节
#define NAME_MAIN       "MAIN\0" //主线程，注意用空格补齐4字节
#define NAME_HTTP       "HTTP\0" //HTTP线程，注意用空格补齐4字节
#define NAME_TCP        "TCP \0" //TCP通讯线程，注意用空格补齐4字节
#define NAME_LOG        "LOG \0" //日志线程，注意用空格补齐4字节

// 线程地址定义
typedef enum task_addr
{
    ADDR_IN         = 'I'<<24 | 'N'<<16 | ' '<<8 | ' ',
    ADDR_OUT        = 'O'<<24 | 'U'<<16 | 'T'<<8 | ' ',
    ADDR_ALL        = 'A'<<24 | 'L'<<16 | 'L'<<8 | ' ',
    
    ADDR_SWITCH     = 'S'<<24 | 'W'<<16 | ' '<<8 | ' ',
    ADDR_MAIN       = 'M'<<24 | 'A'<<16 | 'I'<<8 | 'N',
    ADDR_HTTP       = 'H'<<24 | 'T'<<16 | 'T'<<8 | 'P',
    ADDR_TCP        = 'T'<<24 | 'C'<<16 | 'P'<<8 | ' ',
    ADDR_LOG        = 'L'<<24 | 'O'<<16 | 'G'<<8 | ' ',

    ADDR_UNKONW     = 'U'<<24 | 'N'<<16 | 'K'<<8 | 'O',
}task_addr_t;

#define TASK_ADDR_TO_STRING(addr) (\
    (addr == ADDR_IN)       ? "IN  ":\
    (addr == ADDR_OUT)      ? "OUT ":\
    (addr == ADDR_ALL)      ? "ALL ":\
    (addr == ADDR_SWITCH)   ? "SW  ":\
    (addr == ADDR_MAIN)     ? "MAIN":\
    (addr == ADDR_HTTP)     ? "HTTP":\
    (addr == ADDR_TCP)      ? "TCP ":\
    (addr == ADDR_LOG)      ? "LOG ":\
    "ADDR_UNKNOWN")


//任务方向
typedef enum task_dir
{
    DIR_REQUEST,                   // 请求
    DIR_RESPONSE,                  // 回复
    DIR_NO_RESPONSE                // 不要求回复的请求
}task_dir_t;

//任务类型
typedef enum task_type
{
    /// 应用程序的管理
    TYP_PROG_QUIT           = 0,                          // 程序退出

    /// 线程的管理
    TYP_THRD_REGISTER       = 100,                      // 线程注册
    TYP_THRD_STOP           = 101,                          // 线程退出
    
    /// 外部通讯
    TYP_SERV_START          = 200,                         // 启动管理服务器
    TYP_SERV_NEW_CLIENT     = 201,                    // 有新的客户端
    TYP_SERV_DEL_CLIENT     = 202,                    // 客户端断开连接

    /// 日志模块
    TYP_LOG_GET             = 300,                            // 将日志发送给远端
    TYP_LOG_ENTRY           = 301,                          // 一条日志
    TYP_LOG_LEVEL           = 302,                          // 日志等级
    TYP_LOG_CLIENT_LEVEL    = 303,                   // 调整客户端的日志等级
}task_type_t;

#define TASK_TYPE_TO_STRING(cmd) (\
    (cmd == TYP_PROG_QUIT)          ? "TYP_PROG_QUIT": \
    (cmd == TYP_THRD_REGISTER)      ? "TYP_THRD_REGISTER": \
    (cmd == TYP_THRD_STOP)          ? "TYP_THRD_STOP":\
    (cmd == TYP_SERV_START)         ? "TYP_SERV_START": \
    (cmd == TYP_SERV_NEW_CLIENT)    ? "TYP_SERV_NEW_CLIENT": \
    (cmd == TYP_SERV_DEL_CLIENT)    ? "TYP_SERV_DEL_CLIENT": \
    (cmd == TYP_LOG_GET)            ? "TYP_LOG_GET":\
    (cmd == TYP_LOG_ENTRY)          ? "TYP_LOG_ENTRY":\
    (cmd == TYP_LOG_LEVEL)          ? "TYP_LOG_LEVEL":\
    (cmd == TYP_LOG_CLIENT_LEVEL)   ? "TYP_LOG_CLIENT_LEVEL":\
    "CTL_CMD_UNKNOWN")

//任务携带的数据
typedef struct serv_data
{
    int port;       // 端口
}serv_data_t;

// TYP_LOG_SEND_TO_REMOTE携带的数据
typedef struct log_data
{
    unsigned long ip;
    unsigned int port;
    unsigned int data_size;                                              // 携带的数据长度
    unsigned char  data_buf[TASK_DATA_MAX_SIZE - 12];    // 数据区
}log_data_t;

typedef uint32_t session_t;

// 线程之间通信的任务结构
typedef struct thrd_task_entry
{
    task_addr_t dst;        // 目的线程
    task_addr_t src;        // 源线程
    session_t session;      // 会话ID，可以用于表示一个会话
    task_type_t type;       // 任务类型
    task_dir_t dir;         // 任务方向
    uint32_t seqno;         // 序列号，回复的序列号必须和请求的序列号相同
    uint32_t ttl;           // 存活周期
    uint32_t prio;          // 优先级，数字小优先级高
    uint32_t delay;         // 延时多少时间(ms)发送
    uint32_t data_size;     // 携带的数据长度
    uint8_t *data_buf;      // 数据区
}thrd_task_entry_t;


// 线程通讯队列
typedef struct thrd_task
{
    // 成员变量声明
    UT_array * _queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    // 成员函数声明
    int32_t (* push)(struct thrd_task * pcomm, thrd_task_entry_t * pentry);
    int32_t (* pop)(struct thrd_task * pcomm, thrd_task_entry_t * pentry);
    int32_t (* length)(struct thrd_task * pcomm);
    thrd_task_entry_t * (* front)(struct thrd_task * pcomm, thrd_task_entry_t * pentry);
}thrd_task_t;

// 线程接受的命令
typedef struct thrd_ctl_list_node
{
    task_type_t cmd;
    struct thrd_ctl_list_node * next;
}thrd_ctl_list_node_t;

int register_thrd(const char *name, thrd_task_t *_in_queue, thrd_task_t *_out_queue, pthread_cond_t *cond);
int register_thrd_ctl_cmd(const char *name, thrd_ctl_list_node_t * pnode);
int switch_start();
void switch_stop();

int send_task(
              unsigned int dst,                       // 目的线程
              unsigned int src,                       // 源线程
              unsigned int session,                   // 会话ID，可以用于表示一个会话
              task_type_t type,                       // 任务类型
              task_dir_t dir,                         // 任务方向
              unsigned int seqno,                     // 序列号，回复的序列号必须和请求的序列号相同
              unsigned int data_size,                 // 携带的数据长度
              unsigned char*  data_buf                 // 数据区
              );
int send_task_entry(thrd_task_entry_t *ptask);

#endif // switch_h__
